﻿using System;
using System.Collections.Generic;
using System.Text;
using StarBotDotNet;
using System.Drawing;

namespace StarBotDotNet
{
        public class BuildTarget
        {
 
            private bool IsUnitBuilt()
            {
                return unitToBuild != null;
            }

            private bool HasResources(int min, int gas)
            {
                if (min >= unitToBuild.MineralsCost)
                {
                    if (gas >= unitToBuild.GasCost)
                    {
                        return true;
                    }
                }
                return false;
            }

            BuildStateEnum currentState;
            public BuildStateEnum CurrentState
            {
                get { return currentState; }
            }

            public override string ToString()
            {
                return this.unitToBuild.ToString();
            }

            BuildStateEnum nextState;

            public BuildStateEnum NextState
            {
                get { return nextState; }
            }

            static int nr = 0;

            int currentNr = 0;

            public BuildTarget(UnitType unitToBuild,  int time,UnitType builderType) 
            {
                this.unitToBuild = unitToBuild;
                this.builderType = builderType;
                this.currentState = BuildStateEnum.b0_Initial;
                this.nextState = BuildStateEnum.b0_Initial;
                currentNr = nr;
                nr++;

                Utilities.WriteColorLine(ConsoleColor.Cyan,"Created {0} Time {1} Type {2}", currentNr, time, this.unitToBuild.ToString());
            }

            UnitType builderType;

            public UnitType BuilderType
            {
                get { return builderType; }
            }

            UnitData builder;

            public UnitData Builder
            {
                get { return builder; }
                set { builder = value; }
            }

            UnitType unitToBuild;

            public UnitType UnitToBuild
            {
                get { return unitToBuild; }
                set { unitToBuild = value; }
            }

            UnitData unitProduced;

            public UnitData UnitProduced
            {
                get { return unitProduced; }
                set { unitProduced = value; }
            }

            Point  buildLocation;

            public Point BuildLocation
            {
                get { return buildLocation; }
                set { buildLocation = value; }
            }

            internal bool HasBuilder()
            {
                if (builder == null)
                {
                    return false;

                }

                if (builder.IsDead)
                {
                    return false;
                }

                return true;
            }

            int startBuildTime = -1;

 

            internal bool IsWorking()
            {
                if (!HasBuilder())
                {
                    return false;
                }
                //If the unit is a building
                if (UnitToBuild.Building)
                {
                    //And the builder is idle
                    if (Builder.IsIdle)
                    {
                        return false;
                    }
                }
                else
                {
                    //If the unit is a soldier
                    //And the building is training
                    if (Builder.Unit.IsTraining)
                    {
                        return true;
                    }

                    //The building is not finished yet
                    if (!builder.Unit.IsCompleted)
                    {
                        return true;
                    }
                }
                

                if (builder.Unit.Order == Constants.Order.BuildTerran)
                {
                    return true;
                }

                if (builder.Unit.Order == Constants.Order.Train)
                {
                    return true;
                }

                //if (buildingInitiated)
                //{
                //    return true;
                //}
                return false;



            }

            private int BuildTimeMultiplier = 60;

            private bool TimeHasElapsed(int currentTime)
            {
                if (startBuildTime > 0)
                {
                    
                    if (EstimateTime() < currentTime)
                    {
                        return true;
                    }


                }
                return false;
            }

            public int EstimateTime()
            {
                return startBuildTime + (UnitToBuild.BuildTime * BuildTimeMultiplier);
            }

            public bool LocationReached()
            {
                if (!UnitToBuild.Building)
                {
                    return true;
                }

                if ((Builder.Unit.X == BuildLocation.X) && (Builder.Unit.Y == BuildLocation.Y))
                {
                    return true;
                }

                return false;

            }

  

            internal void InitiateBuilding(ProxyBot bot, int currentTime)
            {
                startBuildTime = currentTime;

                Utilities.WriteColorLine(ConsoleColor.Cyan, "Started: {0} Time {1}", currentNr, startBuildTime);

                if (UnitToBuild.Building)
                {
                    bot.build(Builder.ID, BuildLocation.X, BuildLocation.Y, UnitToBuild.Id);
                }
                else
                {
                    buildLocation = new Point(Builder.Unit.X, Builder.Unit.Y);
                    bot.train(Builder.ID, UnitToBuild.Id);
                }
            }

            bool hasFinishedWithSuccess = false;

            public bool HasFinishedWithSuccess
            {
                get { return hasFinishedWithSuccess; }
            }

            internal void MarkAsSuccessFinished(int timeFinished)
            {
                Utilities.WriteColorLine(ConsoleColor.Cyan, "Finished sucessfully {0} Start {1} End {2} Overdue {3}", currentNr, startBuildTime, timeFinished, CalculateOverdue(timeFinished));

                hasFinishedWithSuccess = true;
                //throw new NotImplementedException();
            }

            internal int CalculateOverdue(int currentTime)
            {
                return currentTime - EstimateTime();
            }

            internal bool IsOverdue(int currentTime)
            {
                return CalculateOverdue(currentTime) > 0;
            }


            internal bool IsMovingToNextState()
            {
                return currentState != nextState;
            }

            internal void MoveToNextState()
            {
                this.currentState = nextState;
            }

            internal void SetIsMovingToNextState(BuildStateEnum nextState)
            {
                this.nextState = nextState;
            }

            internal bool IsBuilderAtLocation()
            {
                throw new NotImplementedException();
            }

            internal bool BuildLocationValid(UnitDictionary currentUnits, ProxyBot bot)
            {
                if (buildLocation.IsEmpty)
                {
                    return false;
                }

                return LocationAnalyzer.LocationValid(BuildLocation.X, BuildLocation.Y, UnitToBuild.TileWidth, UnitToBuild.TileHeight, bot.Map, currentUnits, Builder);

            }

            internal void FindNewBuildLocation(ProxyBot bot, UnitDictionary currentUnits)
            {
                buildLocation = LocationAnalyzer.FindLocationForUnit(UnitToBuild, bot, currentUnits);
                
            }

  

            internal double CalculateDistance(UnitData discovered)
            {
                return this.Builder.Unit.distance(discovered.Unit);
            }

            internal bool BuilderAllocated()
            {
                return (this.Builder != null);
            }

            internal bool BuilderIsRequired()
            {
                if ((currentState == BuildStateEnum.b0_Initial) &&
                    (nextState == BuildStateEnum.b0_Initial))
                {
                    return this.builder == null;
                }
                return false;

            }

            internal bool UsesUnit(UnitData data)
            {
                return data == this.builder;
            }
            bool resourcesAllocated = false;

            public bool ResourcesAllocated
            {
                get { return resourcesAllocated; }
            }

            internal void SetResourcesAllocated()
            {
                resourcesAllocated = true;
            }



            internal bool RequiresBuilder()
            {
                if (currentState == BuildStateEnum.b2_BuilderAndResourcesAllocated)
                {
                    return true;
                }
                if (nextState == BuildStateEnum.b2_BuilderAndResourcesAllocated)
                {
                    return true;
                }
                if (currentState == BuildStateEnum.b3_MovingIntoPosition)
                {
                    return true;
                }

                if (currentState == BuildStateEnum.b5_UnderProduction)
                {
                    //TODO:Not for protoss
                    return true;
                }

                return false;


            }
        }
}
